home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 February: Technology Seed / Mac Tech Seed Feb '97.toast / ODF Release 3 / ODFDev / ODF / Found / FWString / SLTxtPar.cpp < prev    next >
Encoding:
Text File  |  1996-12-16  |  12.9 KB  |  401 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                SLTxtPar.cpp
  4. //    Release Version:    $ ODF 3  $
  5. //
  6. //    Copyright:    (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //========================================================================================
  9.  
  10. #include "FWFound.hpp"
  11.  
  12. #ifndef SLTXTPAR_H
  13. #include "SLTxtPar.h"
  14. #endif
  15.  
  16. #ifndef SLPRIDEB_H
  17. #include "SLPriDeb.h"
  18. #endif
  19.  
  20. #ifndef SLPRIMEM_H
  21. #include "SLPriMem.h"
  22. #endif
  23.  
  24. #ifdef FW_BUILD_MAC
  25. #include <Script.h>
  26. #endif
  27.  
  28. #ifdef FW_BUILD_MAC
  29. #pragma segment Strings
  30. #endif
  31.  
  32. //========================================================================================
  33. //    Platform-dependent constant kTraditionalTextFormat
  34. //========================================================================================
  35. #ifdef FW_BUILD_MAC
  36. #define kTraditionalTextFormat    kODTraditionalMacText
  37. #endif
  38.  
  39. #ifdef FW_BUILD_WIN
  40.     // Include OpenDoc for Windows file that defines kODIBMCodePageText
  41.     #ifndef SOM_Module_include5cStdDefs_OpenDoc_StdDefs_defined
  42.     #include <StdDefs.xh>
  43.     #endif
  44. #define kTraditionalTextFormat    kODIBMCodePageText
  45. #endif
  46.  
  47. //========================================================================================
  48. //    struct FW_ODTradITextData
  49. //========================================================================================
  50.  
  51. struct FW_ODTradITextData
  52. {
  53.     FW_Locale    fLocale;
  54.     char        fText[1];        // Variable length array!
  55. };
  56.  
  57. //========================================================================================
  58. //    Parameter functions for Traditional Text
  59. //========================================================================================
  60.  
  61. const size_t kTradTextOffset = sizeof(FW_Locale);
  62.  
  63. // We declare the following functions extern "C" even though they are static
  64. // (and therefore private to this module) because the FW_ODITextFunctions struct
  65. // expects an array of "C" functions.  A strict type checking compiler such as
  66. // SCpp will not allow you to do it otherwise. - (SFU)
  67.  
  68. extern "C"
  69. {
  70.     static void Trad_GetODITextParams(ODIText* text, 
  71.                                     FW_ODITextParams* params,
  72.                                     FW_PlatformError* error);
  73.     static FW_Boolean Trad_IsCharacterStart(ODIText* text, 
  74.                                     FW_BytePosition, 
  75.                                     FW_BytePosition,
  76.                                     FW_PlatformError* error);
  77.     static FW_BytePosition Trad_GetBytePosition(ODIText* text, 
  78.                                     FW_CharacterPosition,
  79.                                     FW_PlatformError* error);
  80.     static void Trad_SetCapacity(ODIText *text,
  81.                                     long capacity,
  82.                                     FW_Boolean deletePrevBuffer,
  83.                                     FW_PlatformError* error);
  84.     static void Trad_SetLength(ODIText* text, 
  85.                                     long length,
  86.                                     FW_PlatformError* error);
  87.     static void Trad_SetLocale(ODIText* text, 
  88.                                     FW_Locale locale,
  89.                                     FW_PlatformError* error);
  90. }
  91.  
  92. //----------------------------------------------------------------------------------------
  93. // Trad_GetODITextParams
  94. //----------------------------------------------------------------------------------------
  95.  
  96. static void Trad_GetODITextParams(ODIText *text, 
  97.                                     FW_ODITextParams* params,
  98.                                     FW_PlatformError* error)
  99. {
  100.     *error = 0;
  101.     params->fTextStart = (char*) text->text._buffer + kTradTextOffset;
  102.     params->fTextByteLength = text->text._length - kTradTextOffset;
  103.     params->fTextByteCapacity = text->text._maximum - kTradTextOffset;
  104.  
  105.     ODByteArray *array = &text->text;
  106.     FW_ODTradITextData *iTextData = (FW_ODTradITextData *) array->_buffer;
  107.     params->fTextLocale = iTextData->fLocale;
  108. }
  109.  
  110. //----------------------------------------------------------------------------------------
  111. // Trad_IsCharacterStart
  112. //----------------------------------------------------------------------------------------
  113.  
  114. static FW_Boolean Trad_IsCharacterStart(ODIText* text,                                             
  115.                                         FW_BytePosition knownCharacterStartPosition, 
  116.                                         FW_BytePosition positionToCheck,
  117.                                         FW_PlatformError* error)
  118. {
  119.     FW_Boolean result = true;    // assume true, which will be the case for single-byte scripts
  120.     *error = 0;
  121.  
  122.     ODByteArray* array = &text->text;
  123.     FW_ODTradITextData* data = (FW_ODTradITextData *) array->_buffer;
  124.     
  125.     if (!::FW_LocaleIsSingleByte(data->fLocale))
  126.     {
  127. #ifdef FW_BUILD_MAC
  128.         // return true if byte is first byte of a character
  129.         // This doesn't make a distinction between single-byte and double-byte characters
  130.         result = ::CharacterByteType(data->fText+knownCharacterStartPosition, 
  131.                         positionToCheck-knownCharacterStartPosition, 
  132.                         data->fLocale.fScriptCode) != smLastByte;
  133. #endif
  134. #ifdef FW_BUILD_WIN
  135.         // Assume all characters after knownCharacterStartPosition are double-byte characters
  136.         if ((positionToCheck - knownCharacterStartPosition) % 2 != 0)
  137.             result = false;
  138. #endif
  139.     }
  140.  
  141.     return result;
  142. }
  143.  
  144. //----------------------------------------------------------------------------------------
  145. // Trad_GetBytePosition
  146. //----------------------------------------------------------------------------------------
  147.  
  148. static FW_BytePosition Trad_GetBytePosition(ODIText *text, FW_CharacterPosition position,
  149.                                             FW_PlatformError* error)
  150. {
  151.     FW_BytePosition result = position;    // assume single byte characters
  152.     *error = 0;
  153.     
  154.     ODByteArray *array = &text->text;
  155.     FW_ODTradITextData *data = (FW_ODTradITextData *) array->_buffer;
  156.  
  157. #ifdef FW_BUILD_WIN
  158.     if (!::FW_LocaleIsSingleByte(data->fLocale))
  159.     {
  160.         // Assume entire text consists of double-byte characters
  161.         result = position * 2;
  162.     }
  163. #endif
  164.  
  165. #ifdef FW_BUILD_MAC
  166.     if (!::FW_LocaleIsSingleByte(data->fLocale))
  167.     {
  168.         char* p = data->fText;
  169.         short offset = 0;
  170.         short byteType;
  171.         FW_CharacterPosition chPos = 0;
  172.         FW_BytePosition bytePos = 0;
  173.         while (chPos < position)
  174.         {
  175.             byteType = ::CharacterByteType(p, offset, data->fLocale.fScriptCode);
  176.             bytePos++;
  177.             if (byteType == smFirstByte)
  178.             {
  179.                 offset = 1;
  180.             }
  181.             else    // (byteType == smLastByte) || (byteType == smSingleByte)
  182.             {
  183.                 chPos++;
  184.                 p += offset;    // offset is 1 or 0, depending on previous byte
  185.                 p++;
  186.                 offset = 0;
  187.             }
  188.         }
  189.         result = bytePos;
  190.     }
  191. #endif
  192.  
  193.     return result;
  194. }
  195.  
  196. //----------------------------------------------------------------------------------------
  197. // Trad_SetCapacity
  198. //----------------------------------------------------------------------------------------
  199.  
  200. static void Trad_SetCapacity(ODIText *text,
  201.                                     long capacity,
  202.                                     FW_Boolean deletePrevBuffer,
  203.                                     FW_PlatformError* error)
  204. {
  205.     FW_ERR_TRY
  206.     {
  207.         if (capacity > long(text->text._maximum - kTradTextOffset))
  208.         {
  209.             unsigned char *newBuffer = new unsigned char[capacity+kTradTextOffset];
  210.             ::FW_PrimitiveCopyMemory(text->text._buffer, newBuffer, text->text._length);
  211.             if (deletePrevBuffer)
  212.                 delete [] text->text._buffer;
  213.             text->text._buffer = newBuffer;
  214.             text->text._maximum = capacity+kTradTextOffset;
  215.         }
  216.     }
  217.     FW_ERR_CATCH
  218. }
  219.  
  220. //----------------------------------------------------------------------------------------
  221. // Trad_SetLength
  222. //----------------------------------------------------------------------------------------
  223.  
  224. static void Trad_SetLength(ODIText *text, long length, FW_PlatformError* error)
  225. {
  226.     *error = 0;
  227.     FW_PRIV_ASSERT(length <= long(text->text._maximum - kTradTextOffset));
  228.     text->text._length = length + kTradTextOffset;
  229. }
  230.  
  231. //----------------------------------------------------------------------------------------
  232. // Trad_SetLocale
  233. //----------------------------------------------------------------------------------------
  234.  
  235. static void Trad_SetLocale(ODIText *text, FW_Locale locale, FW_PlatformError* error)
  236. {
  237.     *error = 0;
  238.     ODByteArray *array = &text->text;
  239.     FW_ODTradITextData *iTextData = (FW_ODTradITextData *) array->_buffer;
  240.     iTextData->fLocale = locale;    
  241. }
  242.  
  243. //----------------------------------------------------------------------------------------
  244. // gTraditionalFunctions
  245. //----------------------------------------------------------------------------------------
  246.  
  247. FW_ODITextFunctions gTraditionalFunctions = 
  248. {
  249.     Trad_GetODITextParams,
  250.     Trad_IsCharacterStart,
  251.     Trad_GetBytePosition,
  252.     Trad_SetCapacity,
  253.     Trad_SetLength,
  254.     Trad_SetLocale
  255. };
  256.  
  257. //========================================================================================
  258. //    Text Format Registry Functions
  259. //========================================================================================
  260.  
  261. struct PrivRegistryEntry
  262. {
  263.     ODITextFormat            fFormat;
  264.     FW_ODITextFunctions*    fFunctions;
  265. };
  266.  
  267. static PrivRegistryEntry gRegistryMap[] =
  268. {
  269.     { kTraditionalTextFormat, &gTraditionalFunctions }
  270. };
  271.  
  272. const int kNumberFormats = sizeof(gRegistryMap) / sizeof(PrivRegistryEntry);
  273.  
  274. //----------------------------------------------------------------------------------------
  275. // PrivGetFormatFunctions
  276. //----------------------------------------------------------------------------------------
  277.  
  278. static FW_ODITextFunctions* PrivGetFormatFunctions(ODITextFormat format)
  279. {
  280.     // We cache the last format,functions pair used.
  281.     // This not only will speed up the usual case where we're continually
  282.     // just getting the FormatFunctions for the same ODIFormat (e.g. kODTraditionalMacText),
  283.     // it will usually save us from even needing to instantiate the PrivTextFormatMap.
  284.     // Any part that uses kTraditionalTextFormat exclusively will never execute 
  285.     // PrivGetTextFormatMap, so it will never instantiate the map.
  286.     
  287.     static ODITextFormat gLastFormat = kTraditionalTextFormat;
  288.     static FW_ODITextFunctions* gLastFunctions = &gTraditionalFunctions;
  289.     
  290.     FW_ODITextFunctions* result = 0;
  291.     if (format == gLastFormat)
  292.         result = gLastFunctions;
  293.     else
  294.     {
  295.         for (int i=0; i<kNumberFormats; i++)
  296.         {
  297.             if (gRegistryMap[i].fFormat == format)
  298.                 result = gRegistryMap[i].fFunctions;
  299.         }
  300.         if (result)
  301.         {
  302.             gLastFormat = format;
  303.             gLastFunctions = result;
  304.         }
  305.     }
  306.     return result;
  307. }
  308.  
  309. //========================================================================================
  310. //    ODIText Parameter Functions
  311. //========================================================================================
  312.  
  313. //----------------------------------------------------------------------------------------
  314. // FW_TextParams_GetParams
  315. //----------------------------------------------------------------------------------------
  316.  
  317. void FW_TextParams_GetParams(ODIText *text, 
  318.                             FW_ODITextParams* params,
  319.                             FW_PlatformError* error)
  320. {
  321.     FW_ODITextFunctions* functions = PrivGetFormatFunctions(text->format);
  322.     FW_PRIV_ASSERT(functions);
  323.     (functions->fGetParams)(text, params, error);
  324. }
  325.  
  326. //----------------------------------------------------------------------------------------
  327. // FW_TextParams_IsCharacterStart
  328. //----------------------------------------------------------------------------------------
  329.  
  330. FW_Boolean FW_TextParams_IsCharacterStart(ODIText *text,                                             
  331.                                     FW_BytePosition knownCharacterStartPosition, 
  332.                                     FW_BytePosition positionToCheck,
  333.                                     FW_PlatformError* error)
  334. {
  335.     FW_ODITextFunctions* functions = PrivGetFormatFunctions(text->format);
  336.     FW_PRIV_ASSERT(functions);
  337.     return (functions->fIsCharacter)(text, knownCharacterStartPosition, positionToCheck, error);
  338. }
  339.  
  340. //----------------------------------------------------------------------------------------
  341. // FW_TextParams_GetBytePosition
  342. //----------------------------------------------------------------------------------------
  343.  
  344. FW_BytePosition FW_TextParams_GetBytePosition(ODIText *text,
  345.                                     FW_CharacterPosition position,
  346.                                     FW_PlatformError* error)
  347. {
  348.     FW_ODITextFunctions* functions = PrivGetFormatFunctions(text->format);
  349.     FW_PRIV_ASSERT(functions);
  350.     return (functions->fGetBytePos)(text, position, error);
  351. }
  352.  
  353. //----------------------------------------------------------------------------------------
  354. // FW_TextParams_SetCapacity
  355. //----------------------------------------------------------------------------------------
  356.  
  357. void FW_TextParams_SetCapacity(ODIText *text, 
  358.                                 long capacity, 
  359.                                 FW_Boolean deletePrevBuffer,
  360.                                 FW_ODITextParams* params,
  361.                                 FW_PlatformError* error)
  362. {
  363.     FW_ODITextFunctions* functions = PrivGetFormatFunctions(text->format);
  364.     FW_PRIV_ASSERT(functions);
  365.     (functions->fSetCapacity)(text, capacity, deletePrevBuffer, error);
  366.     if (!*error) 
  367.         (functions->fGetParams)(text, params, error);
  368. }
  369.  
  370. //----------------------------------------------------------------------------------------
  371. // FW_TextParams_SetLength
  372. //----------------------------------------------------------------------------------------
  373.  
  374. void FW_TextParams_SetLength(ODIText *text, 
  375.                                 long length, 
  376.                                 FW_ODITextParams* params,
  377.                                 FW_PlatformError* error)
  378. {
  379.     FW_ODITextFunctions* functions = PrivGetFormatFunctions(text->format);
  380.     FW_PRIV_ASSERT(functions);
  381.     (functions->fSetLength)(text, length, error);
  382.     if (!*error) 
  383.         (functions->fGetParams)(text, params, error);
  384. }
  385.  
  386. //----------------------------------------------------------------------------------------
  387. // FW_TextParams_SetLength
  388. //----------------------------------------------------------------------------------------
  389.  
  390. void FW_TextParams_SetLocale(ODIText *text, 
  391.                                 FW_Locale locale,
  392.                                 FW_ODITextParams* params,
  393.                                 FW_PlatformError* error)
  394. {
  395.     FW_ODITextFunctions* functions = PrivGetFormatFunctions(text->format);
  396.     FW_PRIV_ASSERT(functions);
  397.     (functions->fSetLocale)(text, locale, error);
  398.     if (!*error) 
  399.         (functions->fGetParams)(text, params, error);
  400. }
  401.